home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Mac OS / Multiprocessing 2.1v2 SDK / Sample Code / MP Sort Picts 12⁄04⁄99 / Sprocket / Lib / SprocketMain.cp < prev    next >
Encoding:
Text File  |  1999-11-17  |  16.5 KB  |  653 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        SprocketMain.cp
  3.  
  4.     Contains:    The “guts” of a Macintosh application.
  5.  
  6.     Written by: Dave Falkenburg and many other SmartFriends™
  7.  
  8.     Copyright:    © 1993-94 by Dave Falkenburg, all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.      
  12.         <11>    11/16/94    DRF        Added an explicit #include <Traps.h> for latest universal
  13.                                     headers. Also killed off a CFront warning.
  14.         <10>    11/12/94    DRF        Revised QuickDrawGX initialization based on changes made by Jon
  15.                                     Summer. We now use a 'gasz' resource to setup the size of the
  16.                                     graphics heap. Also we are now always TSM aware, not just when
  17.                                     TSMTE is around.
  18.          <9>     11/8/94    DRF        Rolled in LDR’s TSM fixes. Add fonts to the Fonts menu if it
  19.                                     exists. Also, stop openning up the preferences file here.
  20.          <8>     9/27/94    DRF         AppLib.h is now Sprocket.h, also fixed scrap coercion routines
  21.                                      and eliminated HandleUpdate.
  22.          <7>      9/9/94    DRF        Reordered headers and removed redundant #includes.
  23.                                     Conditionalized AOCE support. Also made changes to
  24.                                     TSMEventWrapper to be more like the code in InlineInputSample.
  25.          <6>      9/8/94    DRF        Add HiliteMenu(0) calls after calls to menu handling code
  26.                                     because TSMMenuSelect doesn’t do it. Also reorganized some GX
  27.                                     stuff: allocate and release a graphicsclient (Cam claims this
  28.                                     works on his machine), and turn on all the graphics errors and
  29.                                     notices if qDebug is set.
  30.          <5>      9/7/94    DRF        Rearrange YieldToAnyThread calls to make quitting faster.
  31.          <4>      9/4/94    DRF        Rearrange local variables in HandleMouseDown.
  32.          <3>      9/1/94    DRF        Stop including "MailableWindow.h" here.
  33.          <2>      9/1/94    DRF        More fixes for inline input, but we’re not really done yet.
  34.  */
  35.  
  36. #include "Sprocket.h"
  37.  
  38. #include <limits.h>        //    For LONG_MAX
  39. #include <Multiprocessing.h>
  40. #include <Fonts.h>
  41. #include <Devices.h>
  42. #include <Gestalt.h>
  43. #include <DiskInit.h>
  44. #include <Threads.h>
  45. #include <CodeFragments.h>    //    for kUnresolvedSymbolAddress
  46. #include <Traps.h>
  47. #include <lowmem.h>
  48. #if    qInlineInputAware
  49. #include <TextServices.h>
  50. #include <TSMTE.h>
  51. #endif
  52.  
  53. #if    qUseQuickDrawGX
  54. #include <graphics macintosh.h>
  55. #include <graphics routines.h>
  56. #include <graphics libraries.h>
  57. #include <PrintingManager.h>
  58. #endif
  59.  
  60. #include "StandardMenus.h"
  61. #include "Window.h"
  62. #include "SplashWindow.h"
  63. #include "AppleEventHandling.h"
  64.  
  65.  
  66. //    Function Prototypes
  67.  
  68. void    main(void);
  69. void    MainEventLoop(void);
  70.  
  71. void    HandleMouseDown(TWindow * topWindowObj, EventRecord * anEvent);
  72. void    HandleClose(WindowPtr aWindow);
  73.  
  74.  
  75. //    Globals
  76. Boolean             gHasMPLib = true; //Assume they do
  77. Boolean                gDone = false;
  78. Boolean                gMenuBarNeedsUpdate = true;
  79.  
  80. Boolean                gHasColorQuickdraw = false;
  81. Boolean                gHasThreadManager = false;
  82. Boolean                gHasDragManager = false;
  83. Boolean                gHasAppleScript = false;
  84. Boolean                gHasDisplayManager = false;
  85.  
  86. GrafPtr                gWindowManagerPort;
  87. Rect                gDeskRectangle;
  88. RgnHandle            gMouseRegion = nil;
  89.  
  90. short                gPreferencesRsrcRefNum;
  91.  
  92. #if    qAOCEAware
  93. Boolean                gHasAOCE = false;
  94. #endif
  95.  
  96. #if    qInlineInputAware
  97. Boolean                gHasTextServices = false;
  98. Boolean                gHasTSMTE = false;
  99.  
  100. Boolean                TSMEventWrapperForKotoeri(EventRecord *anEvent);
  101.  
  102. #endif
  103.  
  104. #if    qUseQuickDrawGX
  105. Boolean                gHasQuickDrawGX = false;
  106. long                gQuickDrawGXVersion = 0;
  107. long                gQuickDrawGXPrintingVersion = 0;
  108. gxGraphicsClient    gQuickDrawGXClient;
  109. #endif
  110.  
  111.  
  112. //    Values that can be adjusted by other application code to change
  113. //    the behavior of the MainEventLoop.
  114. //
  115. //    Rules of thumb:
  116. //
  117. //        Increase gXXXRunQuantum (and decrease gXXXSleepQuantum) when:
  118. //            The application has many threads running that need time
  119. //
  120. //        Decrease gXXXRunQuantum when:
  121. //            Sending AppleEvents to other applications
  122. //            Launching other applications
  123. //            Running in the background
  124.  
  125. unsigned long    gForegroundRunQuantum = 0;
  126. unsigned long    gForegroundSleepQuantum = GetCaretTime();
  127. unsigned long    gBackgroundRunQuantum = 0;
  128. unsigned long    gBackgroundSleepQuantum = LONG_MAX;
  129.  
  130.  
  131. //    Globals used to “tune” the performance of MainEventLoop
  132. //    (assume we’ll be starting in the foreground)
  133.  
  134. static    unsigned long    gRunQuantum = gForegroundRunQuantum;
  135. static    unsigned long    gSleepQuantum = gForegroundSleepQuantum;
  136.  
  137. #ifdef    powerc
  138. #ifndef    __MWERKS__
  139. QDGlobals    qd;
  140. #endif
  141. #endif
  142.  
  143. void
  144. main(void)
  145.     {
  146.     long        feature;
  147.  
  148.     MaxApplZone();
  149.     MoreMasters();
  150.     MoreMasters();
  151.     MoreMasters();
  152.     MoreMasters();
  153.  
  154.     InitGraf(&qd.thePort);    
  155.     InitFonts();
  156.     InitWindows();
  157.     InitMenus();
  158.     TEInit();
  159.     InitDialogs(nil);
  160.  
  161.  
  162.     if (Gestalt(gestaltQuickdrawFeatures,&feature) == noErr)
  163.         gHasColorQuickdraw = ((feature & (1 << gestaltHasColor)) != 0);
  164.  
  165.     //InitInterruptSafeDebug(nil);
  166.  
  167.     TSplashWindow * splashWindow = new TSplashWindow;
  168.  
  169.     //    Check for and Initialize QuickDraw GX early on to avoid heap fragmentation
  170.     
  171. #if    qUseQuickDrawGX
  172.     //    Check for and initialize QuickDrawGX
  173.     if (Gestalt(gestaltGXVersion, &gQuickDrawGXVersion) == noErr)
  174.         {
  175.         if (Gestalt(gestaltGXPrintingMgrVersion, &gQuickDrawGXPrintingVersion) == noErr)
  176.             {
  177. #ifdef    powerc
  178.             if ((Ptr) GXEnterGraphics != kUnresolvedSymbolAddress)
  179. #endif
  180.             gHasQuickDrawGX = true;
  181.             }
  182.         }
  183.  
  184.     if (gHasQuickDrawGX)
  185.         {
  186.         // Initialize the graphics and printing environments.
  187.         //    For additional details see "IM: QD GX Environment & Utilities."
  188.         
  189.         //    We let QuickDraw GX look for a resource  of type 'gasz' with an ID of 0.
  190.         //    GX uses the first long word of that resource as the graphics heap size.
  191.         //    To determine the memory requirements of your graphics client heap see:
  192.         //    “IM: QD GX Environment & Utilities pp2-8,2-9”
  193.         
  194.         //    NOTE:    If your application does not provide this resource,
  195.         //            QuickDraw GX version 1.0 uses a default size of 600 KB.
  196.  
  197.         gQuickDrawGXClient = GXNewGraphicsClient(nil, kUseGraphicsSizeResource, kAllowGXToExtendGraphicsHeap);
  198.         if (gQuickDrawGXClient)
  199.             {
  200.             //    NOTE:    GXNewGraphicsClient() does not allocate memory to the heap
  201.             //            until GXEnterGraphics()    is called, so go ahead and call it now
  202.             //            while we have a chance to deal with things nicely.
  203.             //
  204.             // NOTE:    GXEnterGraphics() should only fail if there is not enough memory. 
  205.             
  206.             GXEnterGraphics();
  207.  
  208.             if (GXGetGraphicsError(nil) == noErr)
  209.                 {
  210. #if    qUseQuickDrawGXDebugging
  211.                 // If qUseQuickDrawGXDebugging = TRUE, enable on GX Validation and graphics library errors & notices.
  212.  
  213.                 //    NOTES from Jon Summers:
  214.                 //    As you increase the amount of validation, drawing speed will SLOW
  215.                 //    down due to all of the internal checking. Also, if you play with
  216.                 //    settings enough validation seems to become inconsistent
  217.  
  218.                 GXSetValidation(    //    gxInternalValidation    |
  219.                                     //    gxAllObjectValidation    |
  220.                                     //    gxApHeapValidation        |
  221.                                         gxPublicValidation);        // check parameters to public routines
  222.  
  223.                 //    This functionality will only work with the "debugging" version of QuickDraw GX.
  224.                 //    If you don't have the debugging version installed, these functions will not work. 
  225.  
  226.                 SetGraphicsLibraryErrors();
  227.                 SetGraphicsLibraryNotices();    
  228. #endif
  229.                 if (GXInitPrinting() != noErr)        // See IM: QuickDraw GX Printing
  230.                     {
  231.                     //    We couldn’t initialize printing, so clean up pretend GX isn’t around
  232.                     //    ••• For safety’s sake, we’ll probably want to bail here.
  233.                     
  234.                     if (gQuickDrawGXClient)
  235.                         GXDisposeGraphicsClient(gQuickDrawGXClient);
  236.                     gHasQuickDrawGX = false;
  237.                     }
  238.                 }
  239.             }
  240.         }
  241.  
  242.     if (gQuickDrawGXClient)
  243.         InitCommonColors();        // Initialize the CommonColors Library.
  244. #if    qRequireQuickDrawGX
  245.     else
  246.         FatalErrorAlert(kCoreErrorStrings, kNeedsQuickdrawGX);
  247. #endif    //    qRequireQuickDrawGX
  248. #endif    //    qUseQuickDrawGX
  249.  
  250.  
  251.     if ((Gestalt(gestaltAppleEventsAttr,&feature) == noErr) &&
  252.         (feature & (1 << gestaltAppleEventsPresent)))
  253.         {
  254.         //    Figure out if we need to do AppleEvent recording
  255.         gHasAppleScript = ((feature & (1 << gestaltScriptingSupport)) != 0);
  256.         }
  257.     else
  258.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  259.  
  260. #if    qInlineInputAware
  261.     if ((Gestalt(gestaltTSMgrVersion,&feature) == noErr) && (feature >= 1))
  262.         {
  263.         gHasTextServices = true;
  264.         if (Gestalt(gestaltTSMTEAttr, &feature) == noErr)
  265.             gHasTSMTE = (feature & (1 << gestaltTSMTEPresent));
  266.  
  267.         if (InitTSMAwareApplication() != noErr)
  268.             {
  269.             gHasTextServices = false;
  270.             gHasTSMTE = false;
  271.             }
  272.         }
  273.  
  274. #endif
  275.  
  276.     if (Gestalt(gestaltThreadMgrAttr,&feature) == noErr)
  277.         {
  278. #ifdef    powerc
  279.         //    If running on a PowerPC, make sure that we not only have the
  280.         //    68K Thread Manager, but also the PowerPC shared library, too.
  281.         //    Because of the wonders of weak linking and out of memory errors
  282.         //    we need to also check to make sure that an entrypoint in the library
  283.         //    is there, too. 
  284.         if (long(NewThread) != kUnresolvedCFragSymbolAddress)
  285.             gHasThreadManager = ((feature & ((1 << gestaltThreadMgrPresent) | (1 << gestaltThreadsLibraryPresent))) != 0);
  286. #else
  287.         gHasThreadManager = ((feature & (1 << gestaltThreadMgrPresent)) != 0);
  288. #endif
  289.         }
  290.  
  291. #if    qRequireThreadManager
  292.     if (gHasThreadManager == false)
  293.         FatalErrorAlert(kCoreErrorStrings, kNeedsThreadManager);
  294. #endif
  295.  
  296.     //    Check for and install Drag Manager callbacks
  297.     if (Gestalt(gestaltDragMgrAttr,&feature) == noErr)
  298.         {
  299. #ifdef    powerc
  300.         //    If running on a PowerPC, make sure that we not only have the
  301.         //    68K Drag Manager, but also the PowerPC shared library, too.
  302.         if (long(NewDrag) != kUnresolvedCFragSymbolAddress)
  303.             gHasDragManager = ((feature & ((1 << gestaltDragMgrPresent) | (1 << gestaltPPCDragLibPresent))) != 0);
  304. #else
  305.         gHasDragManager = ((feature & (1 << gestaltDragMgrPresent)) != 0);
  306. #endif
  307.  
  308.         if (gHasDragManager)
  309.             {
  310.             InstallTrackingHandler(NewDragTrackingHandlerProc(CallWindowDragTrackingHandler),(WindowPtr) nil,nil);
  311.             InstallReceiveHandler(NewDragReceiveHandlerProc(CallWindowDragReceiveHandler),(WindowPtr) nil,nil);
  312.             }
  313.         }
  314.  
  315.     //    Check for Display Manager
  316.     if (Gestalt(gestaltDisplayMgrAttr,&feature) == noErr)
  317.         gHasDisplayManager = ((feature & (1 << gestaltDisplayMgrPresent)) != 0);
  318.  
  319. #if    qAOCEAware    
  320.     //    Check for and initialize AOCE Standard Mail package if it exists
  321.     if ((Gestalt(gestaltSMPMailerVersion,&feature) == noErr) && (feature != 0))
  322.         {
  323. #ifdef    powerc
  324.         if ((Ptr) SMPInitMailer != kUnresolvedSymbolAddress)
  325.             gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  326. #else
  327.         gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  328. #endif
  329.         }
  330. #endif
  331.  
  332.     //    Install our AppleEvent Handlers
  333.     InstallAppleEventHandlers();
  334.  
  335.     //    Setup desktop rectangle for dragging windows around            
  336.     GetWMgrPort(&gWindowManagerPort);
  337.     gDeskRectangle = (**GetGrayRgn()).rgnBBox;
  338.  
  339.     //    Get the default menubar
  340.     SetMenuBar(GetNewMBar(rMenuBar));
  341.     AppendResMenu(GetMenuHandle(mApple),'DRVR');
  342.  
  343.     // Add fonts to the font menu if it installed
  344.     if (GetMenuHandle(mFont))
  345.         AppendResMenu(GetMenuHandle(mFont),'FONT');
  346.     
  347.     if (SetupApplication() == noErr)
  348.         {
  349.         delete    splashWindow;    //    get rid of the splash screen
  350.         
  351.         if (!MPLibraryIsLoaded())     { //Don't allow MP tasks
  352.             DisableItem(GetMenuHandle(257),7);
  353.             gHasMPLib = false;
  354.         } else {
  355.         
  356.         }
  357.         MainEventLoop();
  358.         TearDownApplication();
  359.         }
  360.  
  361.  
  362. #if    qInlineInputAware
  363.     if (gHasTextServices)
  364.         (void) CloseTSMAwareApplication();
  365. #endif
  366.         
  367. #if    qUseQuickDrawGX
  368.     //    Tear down QuickDrawGX
  369.     if (gHasQuickDrawGX && gQuickDrawGXClient)
  370.         {
  371.         DisposeCommonColors();
  372.         GXExitPrinting();        // Close the new printing mgr. 
  373.         GXExitGraphics();        // Deallocate all of the default structures
  374.         GXDisposeGraphicsClient(gQuickDrawGXClient);    
  375.         }
  376. #endif
  377.     }
  378.  
  379.  
  380. void
  381. MainEventLoop(void)
  382.     {
  383.     EventRecord        anEvent;
  384.     unsigned long    nextTimeToCheckForEvents = 0;
  385.     
  386.     while (!gDone)
  387.         {
  388.         if (gMenuBarNeedsUpdate)
  389.             {
  390.             gMenuBarNeedsUpdate = false;
  391.             DrawMenuBar();
  392.             }
  393.  
  394.         if (gHasThreadManager)
  395.             YieldToAnyThread();
  396.  
  397.         if ((gRunQuantum == 0) ||
  398.             (TickCount() > nextTimeToCheckForEvents))
  399.             {
  400.             nextTimeToCheckForEvents = TickCount() + gRunQuantum;
  401.             
  402.             (void) WaitNextEvent(everyEvent,&anEvent,gSleepQuantum,gMouseRegion);
  403.                         
  404. #if    qInlineInputAware
  405.             if (gHasTextServices && TSMEventWrapperForKotoeri(&anEvent))
  406.                 {
  407.                 }
  408.             else
  409. #endif
  410.                 HandleEvent(&anEvent);
  411.             }
  412.         }
  413.     }
  414.  
  415. #if    qInlineInputAware
  416.  
  417. Boolean
  418. TSMEventWrapperForKotoeri(EventRecord *anEvent)
  419.     {
  420.     short        oldFont;
  421.     ScriptCode    keyboardScript;
  422.     Boolean        didTSMHandleTheEvent = false;
  423.  
  424.     //    This snippet of code is from TE 27: Inline Input & TextEdit
  425.     //    and is related to working around a bug in Kotoeri, one of the
  426.     //    Japanese Input methods when operating in a mixed script
  427.     //    environment (e.g., Japanese Language Kit)
  428.     
  429.     // make sure we have a port and it's not the Window Manager port
  430.     if (qd.thePort != nil)
  431.         {
  432.         oldFont            = qd.thePort->txFont;
  433.         keyboardScript    = GetScriptManagerVariable(smKeyScript);
  434.  
  435.         if (FontToScript(oldFont) != keyboardScript)
  436.             TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
  437.         }
  438.  
  439.     didTSMHandleTheEvent = TSMEvent(anEvent);
  440.     
  441.     TextFont(oldFont);        //    restore the font, even though the sample code didn’t
  442.  
  443.     return didTSMHandleTheEvent;
  444.     }
  445.  
  446. #endif    
  447.  
  448.  
  449.  
  450. void
  451. HandleEvent(EventRecord *anEvent)
  452.     {
  453.     TWindow    * wobj;
  454.     
  455.     if (anEvent->what != updateEvt)
  456.         wobj = GetWindowObject(FrontNonFloatingWindow());
  457.     else
  458.         wobj = GetWindowObject((WindowPtr) anEvent->message);
  459.  
  460.     if (wobj != nil)
  461. #if    qInlineInputAware
  462.         // give text services a chance to set the cursor shape
  463.         if (gHasTextServices && SetTSMCursor(anEvent->where))
  464.             ;    // do nothing, TSM did it for me
  465.         else    
  466. #endif
  467.             wobj->AdjustCursor(anEvent);
  468.     
  469.     if ((wobj != nil) && wobj->EventFilter(anEvent))
  470.         return;
  471.         
  472.     else switch (anEvent->what)
  473.         {
  474.         case    nullEvent:
  475.             WindowPtr aWindow = LMGetWindowList();
  476.             
  477.             while ( aWindow )
  478.             {
  479.                 wobj = GetWindowObject((WindowPtr) aWindow);
  480.                 if (wobj != nil)
  481.                     wobj->Idle(anEvent);
  482.                 aWindow = (WindowPtr)((WindowPeek)aWindow)->nextWindow;
  483.             }
  484.             break;
  485.             
  486.         case    mouseDown:
  487.             HandleMouseDown(wobj,anEvent);
  488.             break;
  489.         
  490.         case    keyDown:
  491.         case    autoKey:
  492.             if (anEvent->modifiers & cmdKey)
  493.                 {
  494.                 long    menuResult = MenuKey((short) anEvent->message & charCodeMask);
  495. #if    qInlineInputAware
  496.                 if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  497. #endif
  498.                     HandleMenu(wobj,menuResult);
  499.                 HiliteMenu(0);
  500.                 }
  501.             else if (wobj != nil)
  502.                 wobj->KeyDown(anEvent);
  503.             break;
  504.             
  505.         case    updateEvt:
  506.             {
  507.             GrafPtr        oldPort;
  508.             WindowPtr    aWindow = (WindowPtr) anEvent->message;    
  509.                 
  510.             GetPort(&oldPort);
  511.             SetPort(aWindow);
  512.             BeginUpdate(aWindow);
  513.             if (wobj != nil)
  514.                 wobj->Draw();
  515.             EndUpdate(aWindow);
  516.             SetPort(oldPort);
  517.             }
  518.             break;
  519.             
  520.         case diskEvt:
  521.             if (anEvent->message >> 16)
  522.                 {
  523.                 static    Point    where = {50,50};
  524.                 (void) DIBadMount(where,anEvent->message);
  525.                 }
  526.             break;
  527.                 
  528.         case    osEvt:
  529.             switch ((anEvent->message & osEvtMessageMask) >> 24)
  530.                 {
  531.                 case    mouseMovedMessage:
  532.                     break;
  533.                     
  534.                 case    suspendResumeMessage:                    
  535.  
  536.                     SuspendResumeWindows((anEvent->message & resumeFlag) != 0);
  537.  
  538.                     if (anEvent->message & resumeFlag)
  539.                         {
  540.                         if (anEvent->message & convertClipboardFlag)
  541.                             ReadLocalClipboardFromScrap();
  542.  
  543.                         gRunQuantum = gForegroundRunQuantum;
  544.                         gSleepQuantum = gForegroundSleepQuantum;
  545.                         }
  546.                     else
  547.                         {
  548.                         if (anEvent->message & convertClipboardFlag)
  549.                             WriteLocalClipboardToScrap();
  550.                         gRunQuantum = gBackgroundRunQuantum;
  551.                         gSleepQuantum = gBackgroundSleepQuantum;
  552.                         }
  553.  
  554.                     break;
  555.                 }
  556.             break;
  557.         
  558.         case    kHighLevelEvent:
  559.             (void) AEProcessAppleEvent(anEvent);
  560.             break;
  561.             
  562.         default:
  563.             break;
  564.         }
  565.     }
  566.  
  567. void
  568. HandleMouseDown(TWindow * topWindowObj,EventRecord *anEvent)
  569.     {
  570.     WindowPtr    aWindow;
  571.     TWindow        *wobj;
  572.     short        partCode;
  573.  
  574.     partCode = FindWindow(anEvent->where,&aWindow);
  575.     wobj = GetWindowObject(aWindow);
  576.     switch(partCode)
  577.         {
  578.         case    inMenuBar:
  579.             long    menuResult = MenuSelect(anEvent->where);
  580. #if    qInlineInputAware
  581.             if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  582. #endif
  583.                 HandleMenu(topWindowObj,menuResult);
  584.             HiliteMenu(0);
  585.             break;
  586.             
  587.         case    inSysWindow:
  588.             SystemClick(anEvent,aWindow);
  589.             break;
  590.             
  591.         case    inContent:
  592.             if (wobj)
  593.                 {
  594.                 GrafPtr    oldPort;
  595.                 
  596.                 GetPort(&oldPort);
  597.                 SetPort(aWindow);
  598.                 GlobalToLocal(&anEvent->where);
  599.                 wobj->Click(anEvent);
  600.                 SetPort(aWindow);
  601.                 }
  602.             break;
  603.             
  604.         case    inDrag:
  605.             if (wobj)
  606.                 wobj->Drag(anEvent->where);
  607.             break;
  608.             
  609.         case    inGrow:
  610.             if (wobj)
  611.                 wobj->Grow(anEvent->where);
  612.             break;
  613.             
  614.         case    inGoAway:
  615.             if (TrackGoAway(aWindow,anEvent->where))
  616.                 HandleClose(aWindow);
  617.             break;
  618.  
  619.         case    inZoomIn:
  620.         case    inZoomOut:
  621.             if (TrackBox(aWindow,anEvent->where,partCode) && (wobj))
  622.                 wobj->Zoom(partCode);
  623.             break;
  624.             
  625.         default:
  626.             break;
  627.         }
  628.     }
  629.     
  630.  
  631. void
  632. HandleClose(WindowPtr aWindow)
  633.     {
  634.     short    windowKind;
  635.     TWindow    *wobj;
  636.     
  637.     if (aWindow)
  638.         {
  639.         windowKind = ((WindowPeek) aWindow)->windowKind;
  640.         if (windowKind < 0)
  641.             {
  642.             CloseDeskAcc(((WindowPeek)aWindow)->windowKind);
  643.             }
  644.         else if ( ((wobj = GetWindowObject(aWindow)) != nil) &&
  645.                     wobj->CanClose() &&
  646.                     wobj->Close() &&
  647.                     wobj->DeleteAfterClose())
  648.             {
  649.             delete wobj;
  650.             }
  651.         }
  652.     }
  653.